// OpenGL3.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Window.h"
//Typedefs


Window::Window(HINSTANCE hinst){
	hInstance = hinst;
	m_UsePeekMessage = false;
	m_UseWaitMessage = false;
	TCHAR szTitle[100];
	TCHAR szWindowClass[100];

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, 100);
	LoadString(hInstance, IDC_OPENGL3, szWindowClass, 100);

	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= Window::MsgRouter;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= L"OPENGL3";
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
	classAtom = RegisterClassEx(&wcex);
	


	
}

HWND Window::Create(int width, int height){
	SetLastError(0);
	HWND hWnd = CreateWindow(	L"OPENGL3",
								L"TEST",
								WS_VISIBLE,
								0,
								0,
								width,
								height,
								NULL, 
								NULL, 
								hInstance, 
								this);

	
	return hwnd;
}

void Window::Maximize(){
	SetWindowLong(hwnd, GWL_STYLE, 0); //remove all window styles, check MSDN for details

	::ShowWindow(hwnd, SW_SHOW); //display window
}
void Window::ShowWindow(int nCmdShow){
	::ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);
}
// Window::GetMessageHandler returns the address of the registered
// message handler if one exists
MessageHandler* Window::GetMessageHandler(long message)
{
  // m_MsgHandlers is a tyMessageGameMap instance
  tyMessageIterator it = m_MsgHandlers.find(message);
  if(it == m_MsgHandlers.end())
    return nullptr;
  return it->second;
}


// Final message handler version
LRESULT CALLBACK Window::MsgRouter(HWND hWnd, UINT message,
                               	WPARAM wparam, LPARAM lparam)
{
  Window *wnd = 0;
  if(message == WM_NCCREATE)
  {
		// retrieve Window instance from window creation data and associate        
		LPCREATESTRUCT create_struct = reinterpret_cast<LPCREATESTRUCT>(lparam);
		void * lpCreateParam = create_struct->lpCreateParams;
		wnd = reinterpret_cast<Window *>(lpCreateParam);

		wnd->setHWND(hWnd);
		::SetWindowLongPtr(hWnd, GWL_USERDATA, reinterpret_cast<long>(wnd));

		// save window handle
  }
  else
    // retrieve associated Window instance
    wnd = reinterpret_cast<Window *>(::GetWindowLong(hWnd, GWL_USERDATA));

  if(wnd)
  {
    MessageHandler* handler;
    handler = wnd->GetMessageHandler(message);
    if(handler){
		return handler->handle((*wnd), message, hWnd, wparam, lparam);
		}
  }
  LRESULT c = DefWindowProc(hWnd, message, wparam, lparam);
  return c;
}
MessageHandler* Window::RegisterMessageHandler(long message,
                                    MessageHandler* handler)
{
		MessageHandler* m  = nullptr;
		tyMessageIterator it = m_MsgHandlers.find(message);
		if(it != m_MsgHandlers.end())
			m = it->second;
		m_MsgHandlers.insert(std::pair<long,MessageHandler*>(message, handler));
		return m;
	}


// Window::OnDestroy, revisited
long Window::OnDestroy(Window &wnd, HWND hwnd, long param0, long param1)
{
  PostQuitMessage(0);
  wnd.SetExit(true);
  return 0;
}
// Window::OnClose is a static method called in response to WM_CLOSE
long Window::OnClose(Window &wnd, HWND hwnd, long param0, long param1)
{
  DestroyWindow(hwnd);
  return 0;
}

// Window::HandleMessage ties everything together
bool Window::HandleMessages()
{
  static MSG msg;

  //if(!hwnd)
    //throw std::runtime_error(std::string("Window not yet created"));

  if((m_UsePeekMessage)
 	? ::PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)
 	: ::GetMessage(&msg, hwnd, 0, 0))
  {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
  }
  else
  {
    if(IsExit())
    {
      SetExitCode((long)msg.lParam);
      return false;
    }
    if(m_UseWaitMessage)
    WaitMessage();
  }

  return true;
}







